<template>
    <n-loading-bar-provider>
        <n-dialog-provider>
            <n-notification-provider>
                <n-message-provider>
                    <slot></slot>
                    <naive-provider-content />
                </n-message-provider>
            </n-notification-provider>
        </n-dialog-provider>
    </n-loading-bar-provider>
</template>

<script setup lang="ts">
import { defineComponent, h } from 'vue'
import {
    type MessageOptions,
    useDialog,
    useLoadingBar,
    useMessage,
    useNotification
} from 'naive-ui'
import type { MessageApiInjection } from 'naive-ui/es/message/src/MessageProvider'

defineOptions({ name: 'NaiveProvider' })

// 挂载naive组件的方法至window, 以便在路由钩子函数和请求函数里面调用
function registerNaiveTools() {
    window.$loadingBar = useLoadingBar()
    window.$dialog = useDialog()
    window.$message = useMessage()
    window.$success = message('success')
    window.$warning = message('warning')
    window.$error = message('error')
    window.$info = message('info')
    window.$notification = useNotification()
}

function message(
    type: keyof MessageApiInjection
): (content: string, duration?: number, options?: MessageOptions) => Promise<void> {
    return (content: string, duration = 1000, options?: MessageOptions) => {
        return new Promise((resolve) => {
            window.$message?.[type](content, {
                duration,
                ...options,
                onLeave: () => {
                    if (options?.onLeave) {
                        options.onLeave()
                    }
                    resolve()
                }
            })
        })
    }
}

const NaiveProviderContent = defineComponent({
    name: 'NaiveProviderContent',
    setup() {
        registerNaiveTools()
    },
    render() {
        return h('div')
    }
})
</script>
<style scoped></style>
